home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / mouspp / mouse.cpp < prev    next >
C/C++ Source or Header  |  1992-10-07  |  17KB  |  786 lines

  1. /* -------------------------------------------------------------------- */
  2. /* Mouse++ Version 4.0            mouse.cpp            Revised 10/05/92 */
  3. /*                                                                      */
  4. /* General mouse class for Turbo C++/Borland C++.                       */
  5. /* Copyright 1991, 1992 by Carl W. Moreland                             */
  6. /* -------------------------------------------------------------------- */
  7.  
  8. #include <dos.h>
  9. #include "mouse.h"
  10.  
  11. Mouse mouse;
  12. void interrupt RepeatHandler(...);
  13. void interrupt far (*oldInterrupt_1C)(...);
  14.  
  15. /* -------------------------------------------------------------------- */
  16.  
  17. Mouse::Mouse(void)            // reset mouse - constructor
  18. {
  19.   int found;
  20.   unsigned seg, off;
  21.  
  22.   exists  = 0;                // initialize everything
  23.   enabled = 0;
  24.   visible = 0;
  25.   current.button = 0;
  26.   current.x      = 0;
  27.   current.y      = 0;
  28.   current.xcount = 0;
  29.   current.ycount = 0;
  30.   clickThreshold = 250;
  31.   repeatDelay    = 1000;
  32.   repeatRate     = 200;
  33.   handlerInstalled = 0;
  34.   handlerActive = 0;
  35.   current.event = 0x00;
  36.   buffer.Clear();
  37.  
  38.   _AX = 0x00;                // check for the existance of
  39.   geninterrupt(0x33);            //   a mouse
  40.   found   = _AX;
  41.   buttons = _BX;            // also returns # of buttons
  42.  
  43.   if(found)
  44.     exists = 1;
  45.   if(!exists) return;
  46.  
  47.   _ES = 0;
  48.   _DX = 0;
  49.   _CX = 0;                // clear the event handler
  50.   _AX = 0x14;
  51.   geninterrupt(0x33);
  52.   oldHandler.mask    = _CX;        // save the old event handler
  53.   off = _DX;
  54.   seg = _ES;
  55.   oldHandler.offset  = off;
  56.   oldHandler.segment = seg;
  57.  
  58.   _AX = 0x24;                // get some mouse info
  59.   geninterrupt(0x33);
  60.   Info.majorvers = _BH;
  61.   Info.minorvers = _BL;
  62.   Info.type      = _CH;
  63.   Info.irq       = _CL;
  64.  
  65.   oldInterrupt_1C = getvect(0x1C);
  66.   setvect(0x1C, RepeatHandler);
  67. }
  68.  
  69. Mouse::~Mouse(void)            // restore mouse - destructor
  70. {
  71.   if(!exists) return;
  72.  
  73.   _AX = 0x00;                // reset mouse
  74.   geninterrupt(0x33);
  75.  
  76.   if(oldHandler.mask)            // restore old event handler
  77.     InstallHandler(oldHandler);
  78.  
  79.   setvect(0x1C, oldInterrupt_1C);
  80. }
  81.  
  82. void Mouse::Enable(void)        // enable the mouse
  83. {
  84.   if(!exists || enabled) return;
  85.  
  86.   if(currentHandler.mask && !handlerInstalled)
  87.     InstallHandler();            // re-install event handler
  88.  
  89.   enabled = 1;
  90. }
  91.  
  92. void Mouse::Disable(void)        // disable the mouse
  93. {
  94.   if(!exists || !enabled) return;
  95.  
  96.   if(handlerInstalled)
  97.   {
  98.     ClearHandler();            // disable the event handler
  99.     ClearClick();            // clear the multi-click buffers
  100.   }
  101.   Hide();                // turn the cursor off
  102.   enabled = 0;
  103. }
  104.  
  105. void Mouse::Show(void)                // show mouse cursor
  106. {
  107.   if(!exists || !enabled) return;
  108.   if(visible) return;
  109.  
  110.   if(cgcActive)
  111.     cgc->Show();
  112.   else
  113.   {
  114.     _AX = 0x01;
  115.     geninterrupt(0x33);
  116.   }
  117.   visible = 1;
  118. }
  119.  
  120. void Mouse::Hide(void)            // hide mouse cursor
  121. {
  122.   if(!exists || !enabled) return;
  123.   if(visible < 1) return;
  124.  
  125.   if(cgcActive)
  126.     cgc->Hide();
  127.   else
  128.   {
  129.     _AX = 0x02;
  130.     geninterrupt(0x33);
  131.   }
  132.   visible = 0;
  133. }
  134.  
  135. void Mouse::Move(int x, int y)        // move cursor to col, row
  136. {                    // col & row are pixel coordinates
  137.   if(!exists || !enabled) return;
  138.  
  139.   _DX = y;
  140.   _CX = x;
  141.   _AX = 0x04;
  142.   geninterrupt(0x33);
  143. }
  144.  
  145. void Mouse::xLimit(int min, int max)    // set min/max column range
  146. {                    // min & max are pixel coordinates
  147.   if(!exists) return;
  148.  
  149.   _DX = max;
  150.   _CX = min;
  151.   _AX = 0x07;
  152.   geninterrupt(0x33);
  153. }
  154.  
  155. void Mouse::yLimit(int min, int max)    // set min/max row range
  156. {                    // min & max are pixel coordinates
  157.   if(!exists) return;
  158.  
  159.   _DX = max;
  160.   _CX = min;
  161.   _AX = 0x08;
  162.   geninterrupt(0x33);
  163. }
  164.  
  165. void Mouse::xyLimit(int xmin, int xmax, int ymin, int ymax)
  166. {
  167.   xLimit(xmin, xmax);
  168.   yLimit(ymin, ymax);
  169. }
  170.  
  171. int Mouse::GetVideoPage(void)        // get the cursor's display page
  172. {
  173.   if(!exists) return 0;
  174.  
  175.   _AX = 0x1E;
  176.   geninterrupt(0x33);
  177.   return _BX;
  178. }
  179.  
  180. void Mouse::SetVideoPage(int page)    // set the cursor's display page
  181. {
  182.   if(!exists) return;
  183.  
  184.   _BX = page;
  185.   _AX = 0x1D;
  186.   geninterrupt(0x33);
  187. }
  188.  
  189. void Mouse::MickToPix(int horiz, int vert)
  190. {                             // set the mickey to pixel ratio
  191.   if(!exists) return;
  192.  
  193.   _DX = vert;
  194.   _CX = horiz;
  195.   _AX = 0x0F;
  196.   geninterrupt(0x33);
  197. }
  198.  
  199. void Mouse::SetSpeedThreshold(unsigned speed)
  200. {                    // set speed change threshold
  201.   if(!exists) return;
  202.  
  203.   _DX = speed;
  204.   _AX = 0x13;
  205.   geninterrupt(0x33);
  206. }
  207.  
  208. void Mouse::SetCursor(TextCursor& cursor)
  209. {                    // change the text cursor
  210.   int wasVisible = 0;
  211.  
  212.   if(!exists) return;
  213.   if(visible)
  214.   {
  215.     wasVisible = 1;
  216.     Hide();
  217.   }
  218.  
  219.   _DX = cursor.cMask;
  220.   _CX = cursor.sMask;
  221.   _BX = cursor.type;
  222.   _AX = 0x0A;
  223.   geninterrupt(0x33);
  224.   cgcActive = 0;
  225.  
  226.   if(wasVisible)
  227.     Show();
  228. }
  229.  
  230. void Mouse::SetCursor(GraphicsCursor& cursor)
  231. {                    // change the graphics cursor
  232.   int wasVisible = 0;
  233.  
  234.   if(!exists) return;
  235.   if(visible)
  236.   {
  237.     wasVisible = 1;
  238.     Hide();
  239.   }
  240.  
  241.   if(cursor.type == 0)            // std 16x16 cursor
  242.   {
  243.     _ES = FP_SEG(cursor.cImage);
  244.     _DX = FP_OFF(cursor.cImage);
  245.     _CX = cursor.hoty;
  246.     _BX = cursor.hotx;
  247.     _AX = 0x09;
  248.     geninterrupt(0x33);
  249.   }
  250.   else                    // arbitrary cursor size
  251.   {
  252.     _ES = FP_SEG(cursor.cImage);
  253.     _DX = FP_OFF(cursor.cImage);
  254.     _CH = cursor.cHeight;
  255.     _CL = cursor.hoty;
  256.     _BH = cursor.cWords;
  257.     _BL = cursor.hotx;
  258.     _AX = 0x12;
  259.     geninterrupt(0x33);
  260.   }
  261.  
  262.   gc   = &cursor;
  263.   cgcActive = 0;
  264.  
  265.   if(handlerInstalled)            // reinstall the current handler
  266.     InstallHandler();
  267.  
  268.   if(wasVisible)
  269.     Show();
  270. }
  271.  
  272. void Mouse::SetCursor(ColorGraphicsCursor& cursor)
  273. {
  274.   int wasVisible = 0;
  275.  
  276.   if(!exists) return;
  277.   if(visible)
  278.   {
  279.     wasVisible = 1;
  280.     Hide();
  281.   }
  282.  
  283.   cgc  = &cursor;
  284.   cgcActive = 1;
  285.  
  286.   if(handlerInstalled)            // reinstall the current handler
  287.     InstallHandler();
  288.  
  289.   if(wasVisible)            // need to get the current coords
  290.   {
  291.     _AX = 0x03;
  292.     geninterrupt(0x33);
  293.     cursor.x = _CX;
  294.     cursor.y = _DX;
  295.     Show();
  296.   }
  297. }
  298.  
  299. void Mouse::Position(void)        // update cursor position &
  300. {                    // button status
  301.   if(!exists || !enabled) return;
  302.  
  303.   _AX = 0x03;
  304.   geninterrupt(0x33);
  305.   current.button = _BX;
  306.   current.x = _CX;
  307.   current.y = _DX;
  308. }
  309.  
  310. int Mouse::Pressed(int button)        // check press status of button
  311. {
  312.   if(!exists || !enabled) return(0);
  313.  
  314.   if(handlerInstalled)
  315.   {
  316.     if(button == LEFTBUTTON)
  317.       return(current.event & LB_PRESSED);
  318.     else if(button == RIGHTBUTTON)
  319.       return(current.event & RB_PRESSED);
  320.     else if(button == CENTERBUTTON)
  321.       return(current.event & CB_PRESSED);
  322.   }
  323.  
  324.   _BX = button;
  325.   _AX = 0x05;
  326.   geninterrupt(0x33);
  327.   current.button = _AX;
  328.   int BX = _BX;
  329.   if(BX)
  330.   {
  331.     current.x = _CX;
  332.     current.y = _DX;
  333.   }
  334.   return(BX);
  335. }
  336.  
  337. int Mouse::Released(int button)        // check release status of button
  338. {
  339.   if(!exists || !enabled) return(0);
  340.  
  341.   if(handlerInstalled)
  342.   {
  343.     if(button == LEFTBUTTON)
  344.       return(current.event & LB_RELEASED);
  345.     else if(button == RIGHTBUTTON)
  346.       return(current.event & RB_RELEASED);
  347.     else if(button == CENTERBUTTON)
  348.       return(current.event & CB_RELEASED);
  349.   }
  350.  
  351.   _AX = 0x06;
  352.   _BX = button;
  353.   geninterrupt(0x33);
  354.   current.button = _AX;
  355.   int BX = _BX;
  356.   if(BX)
  357.   {
  358.     current.x = _CX;
  359.     current.y = _DX;
  360.   }
  361.   return(BX);
  362. }
  363.  
  364. void Mouse::Motion(void)        // get # of mickeys moved
  365. {
  366.   if(!exists || !enabled) return;
  367.  
  368.   _AX = 0x0B;
  369.   geninterrupt(0x33);
  370.   current.xcount = _CX;
  371.   current.ycount = _DX;
  372. }
  373.  
  374. int Mouse::InBox(int left,  int top,    // see if mouse is in a box
  375.                  int right, int bottom)
  376. {
  377.   if(!exists || !enabled) return(0);
  378.  
  379.   if((current.x >= left)  && (current.y >= top) &&
  380.      (current.x <= right) && (current.y <= bottom))
  381.     return(1);
  382.   return(0);
  383. }
  384.  
  385. void Mouse::Exclude(int left,  int top,    // set up exclusion area
  386.                     int right, int bottom)
  387. {
  388.   static unsigned char hotx, hoty, height, width;
  389.  
  390.   if(!exists || !enabled) return;
  391.  
  392.   if(cgcActive)
  393.   {
  394.     hotx   = cgc->hotx;
  395.     hoty   = cgc->hoty;
  396.     height = cgc->cHeight - 1;
  397.     width  = cgc->cWidth  - 1;
  398.   }
  399.   else
  400.   {
  401.     hotx   = gc->hotx;
  402.     hoty   = gc->hoty;
  403.     height = gc->cHeight - 1;
  404.     width  = gc->cWidth  - 1;
  405.   }
  406.  
  407.   if((current.x >= (left-width+hotx)) && (current.y >= (top-height+hoty)) &&
  408.      (current.x <= (right+hotx)) && (current.y <= (bottom+hoty)))
  409.     Hide();
  410.   else
  411.     Show();
  412. }
  413.  
  414. void Mouse::SetClickThreshold(unsigned time)
  415. {
  416.   clickThreshold = time;        // time is in milliseconds
  417. }
  418.  
  419. int Mouse::MultiClick(int button)    // check for multiple clicks
  420. {
  421.   if(!exists || !enabled) return(0);
  422.  
  423.   return Click[button >> 1].count;
  424. }
  425.  
  426. int Mouse::DoubleClick(int button)     // check for double clicks
  427. {
  428.   if(!exists || !enabled) return(0);
  429.  
  430.   return (Click[button >> 1].count == 2);
  431. }
  432.  
  433. void Mouse::ClearClick(int button)    // clear the MultiClick buffer
  434. {                    //   button = 7 is the default
  435.   if(!exists || !enabled) return;    //   which clears all the buttons
  436.  
  437.   if(button & LEFTBUTTON)
  438.     Click[0].count = 0;
  439.   if(button & RIGHTBUTTON)
  440.     Click[1].count = 0;
  441.   if(button & CENTERBUTTON)
  442.     Click[2].count = 0;
  443. }
  444.  
  445. /* ----- Event Handler routines --------------------------------------- */
  446.  
  447. void interrupt MouseHandler(void)    // default event handler
  448. {
  449.   mouse.Save(_AX,_BX,_CX,_DX,_DI,_SI);  // save the normal stuff
  450.   EventExit();                // required for interrupt function
  451. }
  452.  
  453. void Mouse::InstallHandler(void)
  454. {
  455.   unsigned seg, off;
  456.  
  457.   if(!exists) return;
  458.  
  459.   unsigned char mask = currentHandler.mask;
  460.   if(cgcActive)
  461.     mask |= MOUSE_MOVED;        // ColorGraphicsCursors require this
  462.  
  463.   seg = currentHandler.segment;
  464.   off = currentHandler.offset;
  465.   _ES = seg;
  466.   _DX = off;
  467.   _CX = mask;
  468.   _AX = 0x14;
  469.   geninterrupt(0x33);
  470.  
  471.   handlerInstalled = 1;
  472.   buffer.Clear();
  473. }
  474.  
  475. void Mouse::InstallHandler(unsigned char mask,
  476.                            void interrupt (*handler)(void))
  477. {
  478.   if(!exists) return;
  479.  
  480.   currentHandler.mask    = mask;
  481.   currentHandler.segment = FP_SEG(handler);
  482.   currentHandler.offset  = FP_OFF(handler);
  483.  
  484.   InstallHandler();
  485. }
  486.  
  487. void Mouse::InstallHandler(MouseEventHandler& handler)
  488. {                    // install an event handler
  489.   currentHandler = handler;
  490.   InstallHandler();
  491. }
  492.  
  493. void Mouse::ClearHandler(void)        // clear the event handler
  494. {
  495.   if(!exists) return;
  496.  
  497.   _ES = 0;
  498.   _DX = 0;
  499.   _CX = 0;
  500.   _AX = 0x14;
  501.   geninterrupt(0x33);
  502.  
  503.   handlerInstalled = 0;
  504.   buffer.Clear();
  505. }
  506.                     // save an event to the buffer
  507. void Mouse::Save(int event, int button,
  508.                  int x, int y, int xcount, int ycount)
  509. {
  510.   static unsigned char keymask;
  511.   static unsigned long time;
  512.  
  513.   if(cgcActive && (event & MOUSE_MOVED))
  514.   {
  515.     cgc->x = x;
  516.     cgc->y = y;
  517.  
  518.     if(visible)
  519.       cgc->Move();
  520.  
  521.     if(!(currentHandler.mask & MOUSE_MOVED))
  522.       return;
  523.   }
  524.  
  525.   if(buffer.IsFull())
  526.     return;
  527.  
  528.   if(event & MB_PRESSED)
  529.   {
  530.     time = *(unsigned long far *)MK_FP(0x0040, 0x006C)*55;
  531.     keymask = *(char far *)MK_FP(0x0040, 0x0017);
  532.  
  533.     button += (keymask << 4);
  534.     if(keymask & 0x03)
  535.       button += 0x08;
  536.  
  537.     if(event & LB_PRESSED)
  538.     {
  539.       Repeat[0].count = 0;
  540.       Repeat[0].time  = time;
  541.     }
  542.     if(event & RB_PRESSED)
  543.     {
  544.       Repeat[1].count = 0;
  545.       Repeat[1].time  = time;
  546.     }
  547.     if(event & CB_PRESSED)
  548.     {
  549.       Repeat[2].count = 0;
  550.       Repeat[2].time  = time;
  551.     }
  552.   }
  553.   else
  554.     time = 0;                // no button press so time not needed
  555.  
  556.   buffer.PutEvent(event, button, x, y, xcount, ycount, time);
  557. }
  558.  
  559. void Mouse::GetEvent(void)        // get an event from the buffer
  560. {
  561.   if(!exists || !enabled) return;
  562.  
  563.   if(buffer.HasEvent())            // if an event is available...
  564.   {
  565.     current = buffer.GetEvent();
  566.  
  567.     if(current.time)            // store info for MultiClick()
  568.     {
  569.       if(current.event & LB_PRESSED)
  570.       {
  571.         if((current.time - Click[0].time) < clickThreshold)
  572.           Click[0].count++;
  573.         else
  574.           Click[0].count = 1;
  575.  
  576.         Click[0].time = current.time;
  577.       }
  578.       if(current.event & RB_PRESSED)
  579.       {
  580.         if((current.time - Click[1].time) < clickThreshold)
  581.           Click[1].count++;
  582.         else
  583.           Click[1].count = 1;
  584.  
  585.         Click[1].time = current.time;
  586.       }
  587.       if(current.event & CB_PRESSED)
  588.       {
  589.         if((current.time - Click[2].time) < clickThreshold)
  590.           Click[2].count++;
  591.         else
  592.           Click[2].count = 1;
  593.  
  594.         Click[2].time = current.time;
  595.       }
  596.     }
  597.   }
  598.   else
  599.   {
  600.     current.event  = 0;
  601.     current.xcount = 0;
  602.     current.ycount = 0;
  603.   }
  604. }
  605.  
  606. void Mouse::ClearEvent(void)        // clear the current event
  607. {
  608.   current.event  = 0;
  609.   current.button = 0;
  610.   current.x      = 0;
  611.   current.y      = 0;
  612.   current.xcount = 0;
  613.   current.ycount = 0;
  614. }
  615.  
  616. void Mouse::ClearBuffer(void)        // clear the event buffer
  617. {
  618.   buffer.Clear();
  619. }
  620.  
  621. /* ----- Repeater routines -------------------------------------------- */
  622.  
  623. void interrupt RepeatHandler(...)
  624. {
  625.   (*oldInterrupt_1C)();
  626.   mouse.Repeater();
  627. }
  628.  
  629. void Mouse::Repeater(void)
  630. {
  631.   static int x, y;
  632.   static unsigned char event, button, mbutton, keymask;
  633.   static long time, dtime;
  634.  
  635.   if(repeatRate == 0)            // repeat feature is off
  636.     return;
  637.   if(buffer.IsFull())
  638.     return;
  639.  
  640.   time = *(long far *)MK_FP(0x0040, 0x006C)*55;
  641.  
  642.   _AX = 0x03;                // get the current mouse position
  643.   geninterrupt(0x33);            //  & button status
  644.   button = _BL;
  645.   x = _CX;
  646.   y = _DX;
  647.  
  648.   if(button & LEFTBUTTON & repeatMask)
  649.   {
  650.     mbutton = 0;
  651.     event = LB_PRESSED;
  652.   }
  653.   else if(button & RIGHTBUTTON & repeatMask)
  654.   {
  655.     mbutton = 1;
  656.     event = RB_PRESSED;
  657.   }
  658.   else if(button & CENTERBUTTON & repeatMask)
  659.   {
  660.     mbutton = 2;
  661.     event = CB_PRESSED;
  662.   }
  663.   else
  664.     return;
  665.  
  666.   dtime = time - Repeat[mbutton].time;    // time since the last repeat
  667.  
  668.   if((!Repeat[mbutton].count && (dtime >= repeatDelay)) ||
  669.       (Repeat[mbutton].count && (dtime >= repeatRate)))
  670.   {
  671.     keymask = *(char far *)MK_FP(0x0040, 0x0017);
  672.  
  673.     button += (keymask << 4);        // add it to the button mask
  674.     if(keymask & 0x03)
  675.       button += 0x08;
  676.  
  677.     buffer.PutEvent(event, button, x, y, 0, 0, time);
  678.  
  679.     Repeat[mbutton].count++;        // increment the click count
  680.     Repeat[mbutton].time = time;
  681.   }
  682. }
  683.  
  684. void Mouse::SetRepeatRate(unsigned char button,
  685.                           unsigned delay, unsigned rate)
  686. {
  687.   repeatMask  = button;
  688.   repeatDelay = delay;
  689.   repeatRate  = rate;
  690. }
  691.  
  692. /* ----- EventBuffer methods ------------------------------------------ */
  693.  
  694. int EventBuffer::IsFull(void)
  695. {
  696.   if(headPtr == tailPtr-1)
  697.     return 1;
  698.   if(headPtr == MOUSE_BUFFER_SIZE-1 && tailPtr == 0)
  699.     return 1;
  700.   return 0;
  701. }
  702.  
  703. int EventBuffer::HasEvent(void)
  704. {
  705.   return (headPtr != tailPtr);
  706. }
  707.  
  708. void EventBuffer::PutEvent(unsigned char event, unsigned char button,
  709.                            unsigned x, unsigned y,
  710.                        unsigned xcount, unsigned ycount,
  711.                    unsigned long time)
  712. {
  713.   buffer[headPtr].event  = event;    // store the info in the event buffer
  714.   buffer[headPtr].button = button;
  715.   buffer[headPtr].x      = x;
  716.   buffer[headPtr].y      = y;
  717.   buffer[headPtr].xcount = xcount;
  718.   buffer[headPtr].ycount = ycount;
  719.   buffer[headPtr].time   = time;
  720.  
  721.   if(++headPtr >= MOUSE_BUFFER_SIZE)    // increment the head ptr
  722.     headPtr = 0;
  723. }
  724.  
  725. MouseEvent EventBuffer::GetEvent(void)
  726. {
  727.   MouseEvent event = buffer[tailPtr];
  728.  
  729.   if(++tailPtr >= MOUSE_BUFFER_SIZE)
  730.     tailPtr = 0;
  731.  
  732.   return event;
  733. }
  734.  
  735. void EventBuffer::Clear(void)
  736. {
  737.   headPtr = 0;
  738.   tailPtr = 0;
  739. }
  740.  
  741. /* ----- MouseEventHandler methods ------------------------------------ */
  742.  
  743. MouseEventHandler::MouseEventHandler(void)
  744. {
  745.   mask = 0;
  746.   segment = 0;
  747.   offset  = 0;
  748. }
  749.  
  750. MouseEventHandler::MouseEventHandler(unsigned char mask,
  751.                                      void interrupt (*handler)(void))
  752. {
  753.   this->mask = mask;
  754.   segment = FP_SEG(handler);
  755.   offset  = FP_OFF(handler);
  756. }
  757.  
  758. void MouseEventHandler::Install(void)
  759. {
  760.   mouse.InstallHandler(*this);
  761. }
  762.  
  763. /* ----- Cursor constructors ------------------------------------------ */
  764.  
  765. TextCursor::TextCursor(unsigned sMask, unsigned cMask, int type)
  766. {
  767.   this->sMask = sMask;
  768.   this->cMask = cMask;
  769.   this->type  = type;
  770. }
  771.  
  772. GraphicsCursor::GraphicsCursor(unsigned char hotx, unsigned char hoty,
  773.                                unsigned image[],
  774.                                unsigned char width, unsigned char height,
  775.                                unsigned char type)
  776. {
  777.   cImage     = image;
  778.   this->hotx = hotx;
  779.   this->hoty = hoty;
  780.   cWidth     = width;
  781.   cHeight    = height;
  782.   cWords     = width/16 + (width%16 ? 1 : 0);
  783.   this->type = type;
  784. }
  785.  
  786.